<template>
  <div>
    <div ref="graphViewArea" class="graph-view" style="z-index: 1001;">
      <div
        ref="graphContentArea"
        class="graph-content"
        :style="{ height: `calc(100% - ${dataContnentAreaHeight}px)` }"
      >
        <graph-model
          ref="graphModeVue"
          :data="graphModelData"
          @nodeClick="onModelNodeClick"
          @graphClick="onModelGraphClick"
          @reloadData="reloadData"
          @edgeClick="onModelEdgeClick"
          @show-column="showColumn"
          @delete-current-category="deleteCurrentCategory"
          @update-edge-configure="updateEdgeConfig"
        ></graph-model>
        <graph-analysis-with-g-six
          ref="modelAnalysisG6"
          :data="graphAnalysisData"
          :model-nodes="toGraphAnalysisNodes"
          @save-graph="saveGraph"
          @delete-item="deleteItem"
          @hidden-column="hiddenColumn"
        />
      </div>

      <div
        ref="dataContentArea"
        class="data-content"
        :style="{
          height: dataContnentAreaHeight + 'px',
          transition: `all ${isDataContentBarDragged ? 0 : transitionTime}s`,
        }"
      >
        <div
          class="resize-data-content"
          @mousedown="resizeDataContentHeight($event)"
        ></div>
        <div class="data-bar">
          <div class="tab-left">
            <div class="data-items">
              <div
                v-for="(item, i) in dragBarItems"
                :key="i"
                class="data-item"
                :class="{ active: i === activeDragBarItemIndex }"
                @click="clickSourceDataItem(i)"
              >
                {{ item.label }}
              </div>
            </div>
            <!-- 历史记录icon -->
            <a-icon-font
              v-show="showHistoryAction"
              class="graph-list-icon"
              :class="{ 'icon-active': isShowHistory }"
              type="iconqingxi-caozuojilu"
              @click="toggleHistoryMode()"
            />
          </div>
          <!-- 折叠 icon -->
          <a-tooltip
            placement="top"
            class="right-side"
            @click="clickHideButton"
          >
            <span slot="title">{{ isDataContentHide ? '显示' : '隐藏' }}</span>
            <a-icon-font
              v-if="isDataContentHide"
              type="iconxiangshangjiantou"
            />
            <a-icon-font v-else type="iconicon-beifen" />
          </a-tooltip>
        </div>
        <div v-if="noData" class="data-empty">
          <div>
            <img alt="" src="@/assets/view/dataview-empty.svg" />
            <div>暂无数据，请先导入~</div>
          </div>
        </div>
        <div v-else class="data-area">
          <!-- 历史操作记录 -->
          <graph-node-history
            v-show="showHistoryActionList"
            :is-show-history="isShowHistory"
            :graph-id="graphId"
            @delete-action="deleteAction"
            @toggle-history-mode="(value) => (isShowHistory = value)"
          />
          <div class="middle-container">
            <!-- 数据卡片 column -->
            <graph-data-column
              :table-name="tableName"
              :task-id="taskId"
              class="data-columns"
              @add-action="addAction"
              @add-attribute="addAttribute"
              @cancel-attribute="cancelAttribute"
              @change-semantic="changeSemantic"
            />
            <div
              class="resize-data-table-content"
              @mousedown="resizeDataContentHeight($event)"
            ></div>
            <!-- 数据表 -->
            <graph-table class="data-table" @close-modal="closeGraphPanel" />
          </div>
        </div>
      </div>
      <div class="close" @click="closeGraphPanel">
        <a-icon title="关闭" type="close" />
      </div>
      <div
        class="edge-config"
        :style="{
          width: edgeSetDrawerStatus ? '574px' : 0,
          boxShadow: edgeSetDrawerStatus
            ? '0 10px 10px 10px rgba(88, 98, 230, 0.2)'
            : 'none',
        }"
      >
        <node-connection-config
          :data="graphEdgeData"
          :config-data="edgeConfigData"
          @set-connection-config="setConnectionConfig"
        />
      </div>
    </div>
    <div class="ant-modal-mask" style="z-index: 1000;"></div>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
import GraphViewStore from '@/store/modules/graphview'
import GraphBuild from '@/store/modules/graphbuild'
import GraphTable from '@/components/studio/data/node-edit-panel/GraphTable.vue'
import GraphDataColumn from '@/components/studio/data/node-edit-panel/GraphDataColumn.vue'
import GraphModel from '@/components/graph/graphModel.vue'
import GraphAnalysisWithGSix from '@/components/graph/GraphAnalysisWithGSix.vue'
import NodeConnectionConfig from '@/components/graph/nodeConnectionConfig.vue'
import graphNodeHistory from '@/components/graph/graphNodeHistory.vue'
import { getLightColor, getDarkColor } from '@/components/graph/graph-util'
import {
  graphQueryDataTable,
  tcolumnQueryDetail,
  graphQueryFullInputById,
  graphBatchUpdate,
  graphQueryEdgeConfigure,
  graphCloseSession,
} from '@/api/visualization'
import { debounce, cloneDeep } from 'lodash'

// @ts-ignore
const elementResizeDetectorMaker = require('element-resize-detector')

enum DragBarMode {
  SOURCEDATA,
  NODEDATA,
}

@Component({
  components: {
    GraphAnalysisWithGSix,
    GraphDataColumn,
    GraphTable,
    GraphModel,
    NodeConnectionConfig,
    graphNodeHistory,
  },
  directives: {
    focus: {
      inserted: (element: any) => {
        element.focus()
      },
    },
  },
})
export default class GraphView extends Vue {
  public edgeConfigStatus: boolean = false // 节点连接编辑状态
  public dataContnentAreaHeight = 380 // 数据编辑区高度
  public originDataContnentAreaHeight = 380
  public mouseLastPosition = { x: 0, y: 0 }

  public isDataContentBarDragged: boolean = false // 节点编辑面板是否在拖动改变高度
  public transitionTime: number = 0 // 节点编辑面板动画时间

  public activeDragBarItemIndex = 0 // 当前激活的 tab index
  public tableName: string = '' // 表名
  public dragBarItems: Array<{ label: string; tableName: string }> = [] // tab bar list
  public sourceTables: Array<{ label: string; tableName: string }> = [] //
  public graphModelData: object = {}
  public graphAnalysisData: any = {}
  public graphAnalysisDataBackup: any = {}
  public isDataContentHide: boolean = false
  public graphEdgeData: any = {
    id: '',
    source: { label: '' },
    target: { label: '' },
  }
  public edgeConfigData: any = {}
  public toGraphAnalysisNodes: any = null // 将节点信息传给分析模块 用于搜索功能
  private taskId: number = 0 // 节点 Id
  private projectId: number = 0 // 项目 Id
  private graphId: number = 0 // 当前 graphId
  public noData = false // 标记此组件是否有数据传入
  private isShowHistory: boolean = false // 是否显示历史记录
  private paginationParams = {
    curPage: 1,
    name: '_record_id_', // 如果没有字段，那就固定传 _record_id_
    pageSize: 50,
    filter: [],
  }

  // 历史操作 icon 显示
  private get showHistoryAction(): boolean {
    return GraphViewStore.dragBarMode === DragBarMode.NODEDATA
  }
  // 历史操作列表 显示
  private get showHistoryActionList(): boolean {
    return this.isShowHistory && this.showHistoryAction
  }
  // toggle icon status
  public toggleHistoryMode() {
    this.isShowHistory = !this.isShowHistory
  }
  // graph ID
  public getGraphId(): number {
    return Number.parseInt(localStorage.getItem('graphId') || '0', 10)
  }
  // 网络构建中选择的边
  public get selectedEdge() {
    return GraphBuild.selectedEdge
  }
  // 网络构建边配置抽屉状态
  public get edgeSetDrawerStatus() {
    return GraphBuild.edgeSetDrawerStatus
  }

  private get currentHistory() {
    return GraphBuild.currentSelectedHistory || { data: {} }
  }

  /**
   *  生命周期 created
   */
  public created() {
    GraphBuild.setEdgeSetDrawerStatus(false) // 初始化 关闭 边配置状态
    this.projectId = Number(this.$route.params.id)
    this.taskId = Number(this.$route.params.taskid)
    GraphBuild.queryTaskInfoById(this.taskId)
    GraphBuild.queryUserInfo() // 查询用户信息

    GraphViewStore.setGraphSourceTables([])
    GraphViewStore.setGraphAnalysisData({})
    GraphViewStore.setDragBarMode(DragBarMode.SOURCEDATA)
    GraphViewStore.setProjectId(this.projectId)
    GraphViewStore.setTaskId(this.taskId)
    GraphViewStore.setTableData({ head: [], data: [] })

    graphQueryFullInputById({
      data: {
        id: this.taskId,
        projectId: this.projectId,
      },
    }).then((response) => {
      GraphBuild.setTableData(response.data.result.data.input)

      response.data.result.data.input.forEach((item: any) => {
        this.sourceTables.push({
          label: item.nodeName,
          tableName: item.tableName,
        })
      })

      GraphViewStore.setGraphSourceTables(this.sourceTables)

      if (this.sourceTables && this.sourceTables.length > 0) {
        this.resetDragBarData(this.sourceTables)
        this.loadData()
      } else if (!this.sourceTables || this.sourceTables.length <= 0) {
        // 无数据
        this.noData = true
      }
    })
  }

  /**
   *  生命周期 mounted
   */
  public mounted() {
    const saveGraphSize = debounce((element) => {
      GraphViewStore.setGraphSize({
        width: Math.floor(element.offsetWidth / 2),
        height: element.offsetHeight,
      })
    }, 500)

    // 改为实时监听模式，避免表格高度不同步的情况
    this.$nextTick(() => {
      const erd = elementResizeDetectorMaker()
      const graphContentArea = this.$refs.graphContentArea as HTMLElement
      const nodeEditBox = this.$refs.dataContentArea as HTMLElement

      erd.listenTo(graphContentArea, (element: HTMLElement) => {
        saveGraphSize(element)
      })

      erd.listenTo(nodeEditBox, (element: HTMLElement) => {
        // 在firefox无法监听到
        GraphViewStore.setTableHeight(element.offsetHeight - 40 - 270) // 40: data-bar + resize-data-content 高度，270: GraphDataColumn 高度
      })
      this.$once('hook:beforeDestroy', () => {
        erd.removeAllListeners(graphContentArea)
        erd.removeAllListeners(nodeEditBox)
      })
    })
  }

  /**
   * 生命周期 create 请求pipeline 图构建节点 相关数据成功后 loadData
   */
  private loadData() {
    this.loadGraphData()
    this.loadSourceTableData()
  }

  /**
   * 根据 pipeline 图构建节点 id 获取全部graph相关 节点 边信息
   */
  public async loadGraphData() {
    // init graph data
    await graphQueryDataTable({
      data: {
        taskId: this.taskId,
      },
    }).then((response) => {
      const { result } = response.data
      this.graphId = Number.parseInt(result.id, 10)
      localStorage.setItem('graphId', result.id)
      this.loadGraphModelData(result.categories, result.edges)
      if (
        result.nodes.length > 0 &&
        'x' in result.nodes[0] &&
        'y' in result.nodes[0]
      ) {
        this.loadGraphAnalysisData(
          result.categories,
          result.nodes,
          result.links
        )
      }
    })
  }

  /**
   * 关闭graph view modal（右上角 X）
   */
  public closeGraphPanel() {
    const data: any = {
      graphId: this.getGraphId(),
    }
    graphCloseSession({ data }).then((response: any) => {
      if (response.data.code === 100) {
        this.$router.push({ name: '数据视图' })
      }
    })
  }

  /** ================ 构建  选择边 edge 节点 node 相关 start =================== */

  /**
   * 加载点击事件
   * $emit (graph-model)
   */
  public reloadData(result: any) {
    this.loadGraphAnalysisData(result.categories, result.nodes, result.links)
  }

  /**
   * 右侧 加载网络分析的信息
   * 1.进入时加载 2.点击执行 icon 时加载
   */
  private loadGraphAnalysisData(categories: [], nodes: [], links: []) {
    if (nodes.length <= 0) {
      GraphBuild.setIsBuildingGraph(3)
      return
    }
    this.graphAnalysisData = {
      categories,
      nodes: nodes.map((node: any) => {
        node.style.stroke = node.style.fill
        node.style.lineWidth = 4
        node.stateStyles = {
          hover: {
            stroke: getLightColor(node.style.fill, 0.5),
            cursor: 'pointer',
          },
          selected: {
            fill: node.style.fill,
            stroke: getDarkColor(node.style.fill, 0.2),
            shadowBlur: 0,
          },
          putAsh: {
            strokeOpacity: 0.3,
            fillOpacity: 0.3,
          },
          highlighted: {
            stroke: getDarkColor(node.style.fill, 0.2),
          },
        }
        return node
      }),
      links: links.map((link: any) => {
        link.style.endArrow = link.directed
        link.type = link.target === link.source ? 'loop' : link.type
        return link
      }),
    }
    this.graphAnalysisDataBackup = cloneDeep(this.graphAnalysisData) // 备份
    this.toGraphAnalysisNodes = categories
    GraphViewStore.setGraphAnalysisData(this.graphAnalysisData)
  }

  /**
   * 点击 graph 取消选择元素
   * $emit (graph-model)
   */
  public onModelGraphClick() {
    GraphBuild.setEdgeSetDrawerStatus(false) // 关闭抽屉
    if (GraphViewStore.dragBarMode === DragBarMode.SOURCEDATA) {
      return
    }
    GraphViewStore.setDragBarMode(DragBarMode.SOURCEDATA)
    this.resetDragBarData(this.sourceTables)
    this.loadSourceTableData()
  }

  /**
   * 目前删除当前选中的节点 和点击画布同样的效果
   */
  public deleteCurrentCategory() {
    this.onModelGraphClick()
  }

  /**
   * 点击选择节点
   * $emit (graph-model)
   */
  public onModelNodeClick(data: any) {
    if (
      GraphViewStore.dragBarMode === DragBarMode.NODEDATA &&
      this.dragBarItems[0].tableName === data.tableName
    ) {
      return
    }
    GraphViewStore.setDragBarMode(DragBarMode.NODEDATA)
    this.queryCurrentNodeHistory() // 查询历史记录
    this.resetDragBarData([data])
  }

  /**
   * 查询当前节点的历史记录, 选中某个节点， 更改后， 都要更新历史列表
   */
  public async queryCurrentNodeHistory() {
    await GraphBuild.getHistoryList(this.graphId)
    // const {historyList} = await GraphBuild.getHistoryList(this.graphId)
  }

  /**
   * 当前选择的 边
   */
  @Watch('selectedEdge', { deep: true })
  public selectedEdgeChange(edge: any) {
    if (edge) {
      GraphBuild.setEdgeSetDrawerStatus(true)
      const data = {
        id: edge.model.id,
        source: edge.source._cfg.model,
        target: edge.target._cfg.model,
      }
      // 有当前选择的边后 处理边配置需要的相关操作
      this.onModelEdgeClick(data)
    } else {
      GraphBuild.setEdgeSetDrawerStatus(false)
    }
  }

  @Watch('currentHistory')
  public onCurrentHistoryChange() {
    this.tableName = this.currentHistory && this.currentHistory.data.table
    this.loadSourceTableData()
  }

  public updateEdgeConfig() {
    if (this.selectedEdge) {
      const data = {
        id: this.selectedEdge.model.id,
        source: this.selectedEdge.source._cfg.model,
        target: this.selectedEdge.target._cfg.model,
      }
      // 有当前选择的边后 处理边配置需要的相关操作
      this.onModelEdgeClick(data)
    }
  }

  /**
   * model 点击边 edge， store 存储的边改变
   */
  public onModelEdgeClick(data: any) {
    this.cleanEdgeData(data) // 当前组件记录该边相关信息
    this.GetEdgeConfigure()
  }

  /**
   * 当前记录 该边的相关信息， 并传值给自组件 nodeConnectionConfig.vue
   * @param data
   */
  public cleanEdgeData(data: any) {
    const sourceNode = data.source
    const targetNode = data.target

    const edgeData = {
      id: data.id,
      sourceNode,
      targetNode,
      source: {
        label: sourceNode.label,
        tableName: sourceNode.tableName,
      },
      target: {
        label: targetNode.label,
        tableName: targetNode.tableName,
      },
    }
    this.graphEdgeData = edgeData
  }

  /**
   * 查询边配置连接推荐，返回值包含auto-join结果
   */
  public GetEdgeConfigure() {
    graphQueryEdgeConfigure({
      data: {
        graphId: this.graphId,
        edgeId: this.graphEdgeData.id,
      },
    }).then((response: any) => {
      this.edgeConfigData = response.data.result
      this.edgeConfigData.id = this.graphEdgeData.id
      this.edgeConfigData.sourceLabel = this.graphEdgeData.source.label
      this.edgeConfigData.targetLabel = this.graphEdgeData.target.label
      // this.$emit('reloadData', result)
    })
  }

  /** ================ 构建 选择边 edge 节点 node 相关 end =================== */

  /** =============== 网络分析 保存节点边的信息 start  ============ */

  /**
   * 第一次构建-加载画布（点击执行）稳定后保存
   * $emit (analysis-graph）
   */
  public saveGraph(graphInfoWithGraphSize: any) {
    const { size } = graphInfoWithGraphSize
    // 节点
    const newNodes = this.graphAnalysisData.nodes.map((node: any) => {
      return {
        attrs: node.attrs,
        categoryId: node.categoryId,
        id: node.id,
        label: node.label ? node.label : node.nLabel,
        labelCfg: node.labelCfg,
        orderId: node.orderId, // orderId: number 2021.5.26 添加
        size: node.size,
        style: {
          fill: node.style.fill,
        },
        type: node.type,
        x: node.x,
        y: node.y,
      }
    })
    // 边
    const newLinks = this.graphAnalysisData.links.map((link: any) => {
      return {
        attrs: link.attrs,
        directed: link.directed,
        edgeId: link.edgeId,
        id: link.id,
        label: link.label,
        labelCfg: link.labelCfg,
        orderId: link.orderId, // orderId: number 2021.5.26 添加
        source: link.source,
        style: {
          lineWidth: link.style.lineWidth,
          stroke: link.style.stroke,
          endArrow: link.style.endArrow,
        },
        target: link.target,
        type: link.type,
        weight: link.weight,
      }
    })

    const data: any = {
      graphId: this.graphId,
      links: newLinks,
      nodes: newNodes,
      size,
    }
    graphBatchUpdate({ data })
      .then((response: any) => {
        if (response.data.code === 100) {
          GraphBuild.setGraphSaveStatus({
            type: 2,
            lastSaveTime: new Date().getTime(),
          })
          this.$message.success('graph 已更新存储！')
          GraphBuild.setFirstSaveGraphAnalysis(false)
          GraphBuild.setIsBatchSave(true)
          this.graphAnalysisDataBackup = cloneDeep(this.graphAnalysisData)
        } else {
          GraphBuild.setGraphSaveStatus({
            type: 3,
            lastSaveTime: new Date().getTime(),
          })
          this.$message.error('保存失败！')
        }
      })
      .catch(() => {
        GraphBuild.setGraphSaveStatus({
          type: 3,
          lastSaveTime: new Date().getTime(),
        })
      })
  }

  /**
   * 删除数据 节点和边 （analysis-graph）
   */
  public deleteItem(deleteInfo: any) {
    const newNodes = this.graphAnalysisData.nodes.filter(
      (node: any) => !deleteInfo.nodeIds.includes(node.id)
    )
    const newLinks = this.graphAnalysisData.links.filter(
      (link: any) => !deleteInfo.linkIds.includes(link.id)
    )
    this.graphAnalysisData.nodes = newNodes
    this.graphAnalysisData.links = newLinks
    this.graphAnalysisDataBackup = cloneDeep(this.graphAnalysisData) // 备份
    GraphViewStore.setGraphAnalysisData(this.graphAnalysisData)
  }

  /** =============== 下方数据  start ======================== */

  /**
   * 点击 tab 表数据
   */
  public clickSourceDataItem(index: number) {
    this.activeDragBarItemIndex = index
    this.tableName = this.dragBarItems[this.activeDragBarItemIndex].tableName
    // reload data detail
    this.loadSourceTableData()
  }

  /**
   * 设置当前的 节点表
   */
  private resetDragBarData(dataBarItems: Array<any>) {
    this.dragBarItems.length = 0
    this.activeDragBarItemIndex = 0
    dataBarItems.forEach((item) => {
      this.dragBarItems.push(item)
    })
    this.tableName = this.dragBarItems[this.activeDragBarItemIndex].tableName
  }

  /**
   * 加载表数据
   */
  private loadSourceTableData() {
    tcolumnQueryDetail({
      data: {
        ...this.paginationParams,
        table: this.tableName,
        taskId: this.taskId,
      },
    }).then((response) => {
      const dataResult = response.data.result
      this.adjustSourceTableColumn(dataResult)
    })
  }

  private adjustSourceTableColumn(dataResult: any) {
    // 如果当前为选中节点，调整数据表格中字段的显示顺序，与属性列表中的字段顺序保持一致
    if (GraphViewStore.dragBarMode === DragBarMode.NODEDATA) {
      const currentNode = GraphViewStore.currentCategoryData
      const attributeList = [currentNode.keyAttr.column]
      currentNode.attrs.forEach((attribute: any) => {
        attributeList.push(attribute.column)
      })
      for (let i = attributeList.length - 1; i >= 0; i -= 1) {
        const attributeName = attributeList[i]
        const elementIndex = dataResult.head.findIndex((header: any) => {
          return header.name === attributeName
        })
        const element = dataResult.head[elementIndex]
        dataResult.head.splice(elementIndex, 1)
        dataResult.head.unshift(element)
      }
    }
    GraphViewStore.setTableData(dataResult)
  }

  /**
   * 加载左侧网络构建的数据
   */
  private loadGraphModelData(categories: [], edges: []) {
    this.toGraphAnalysisNodes = categories
    this.graphModelData = {
      nodes: categories.map((category: any) => {
        category.type = 'graph-model-node'
        return category
      }),
      edges,
    }
  }

  public deleteAction(info: any) {
    // 通知 graphModel.vue 需要更新当前节点的表,
    const graphModeVue: any = this.$refs.graphModeVue as Vue
    graphModeVue.updateNodeTableById(info)
  }

  /**
   * 表有操作， 更新表(修改字段类型， 修改 name, 筛选)
   * $emit (graph-data-column)
   */
  public addAction(info: any) {
    // 通知 graphModel.vue 需要更新当前节点的表,
    const graphModeVue: any = this.$refs.graphModeVue as Vue
    graphModeVue.updateNodeTableById(info)

    GraphViewStore.setDragBarMode(DragBarMode.NODEDATA)
    const data = {
      label: info.category.label,
      tableName: info.category.tableInfo.tableName,
    }
    this.resetDragBarData([data]) // 更新当前数据显示的内容， 更新显示
    this.queryCurrentNodeHistory() // 操作成功， 更新历史
  }

  /**
   * 当前节点添加属性， 图构建 伪造 tooltip 提示
   */
  public addAttribute(addInfo: any) {
    const graphModeVue: any = this.$refs.graphModeVue as Vue
    graphModeVue.addAttributeToNode(addInfo)

    this.adjustSourceTableColumn({
      head: GraphViewStore.tableColumns,
      data: GraphViewStore.tableData,
    })
  }

  /**
   * 取消当前节点的某个属性
   */
  public cancelAttribute() {
    this.adjustSourceTableColumn({
      head: GraphViewStore.tableColumns,
      data: GraphViewStore.tableData,
    })
  }

  /**
   * 表有操作， 修改语义
   * $emit (graph-data-column)
   */
  public changeSemantic(info: any) {
    const graphModeVue: any = this.$refs.graphModeVue as Vue
    graphModeVue.updateSemanticById(info)
  }

  /** =============== 下方数据  end ======================== */

  /**
   * 拖拽节点 落点
   * @param dragInfo {node, event}
   */
  private dragPosition(dragInfo: any) {
    const reference: any = this.$refs.graph as Vue
    reference.dragToNode(dragInfo)
  }

  /**
   * 改变数据编辑模块高度
   */
  public resizeDataContentHeight($event: MouseEvent) {
    $event.stopPropagation()
    this.dataContentAreaMaxHeight = (this.$refs
      .graphViewArea as HTMLElement).getBoundingClientRect().height
    this.mouseLastPosition = { x: $event.screenX, y: $event.screenY }
    this.isDataContentBarDragged = true
    document.addEventListener('mouseup', this.dragMouseUpListener)
    document.addEventListener('mousemove', this.dragMouseMoveListener)
  }

  private dataContentAreaMaxHeight: number = 0 // 数据编辑模块最大高度

  public dragMouseMoveListener({ screenX, screenY }: MouseEvent) {
    const dy = screenY - this.mouseLastPosition.y
    this.$nextTick(() => {
      if (
        this.dataContnentAreaHeight >= 38 &&
        this.dataContnentAreaHeight <= this.dataContentAreaMaxHeight
      ) {
        let height: number = this.dataContnentAreaHeight - dy
        if (height < 38) {
          height = 38
        }
        if (height > this.dataContentAreaMaxHeight) {
          height = this.dataContentAreaMaxHeight
        }
        this.dataContnentAreaHeight = height
        this.mouseLastPosition = { x: screenX, y: screenY }

        // 在此处更新表格的高度，修复在firefox无法监听的问题
        GraphViewStore.setTableHeight(height - 40 - 270) // 40: data-bar + resize-data-content 高度，270: GraphDataColumn 高度
      }
    })
  }

  public async dragMouseUpListener() {
    document.removeEventListener('mousemove', this.dragMouseMoveListener)
    document.removeEventListener('mouseup', this.dragMouseUpListener)
    // this.setDataCleanTableHeight()
    this.isDataContentBarDragged = false
  }

  /**
   * analysis 有操作 隐藏
   */
  public hiddenColumn() {
    this.clickHideButton()
  }

  // 显示表格数据
  public showColumn() {
    this.isDataContentHide = false
    this.dataContnentAreaHeight = this.originDataContnentAreaHeight
  }

  // 隐藏表格数据
  public clickHideButton() {
    this.isDataContentHide = !this.isDataContentHide
    if (this.isDataContentHide) {
      this.originDataContnentAreaHeight = this.dataContnentAreaHeight
      this.dataContnentAreaHeight = 38
    } else {
      this.dataContnentAreaHeight = this.originDataContnentAreaHeight
    }
  }

  public setConnectionConfig(config: any) {
    const graphModeVue: any = this.$refs.graphModeVue as Vue
    graphModeVue.updateEdgeConnectionConfig(config)
  }
}
</script>

<style lang="less" scoped>
@import '@/constants';

.studio {
  .studio-view {
    overflow: unset;
  }
}
/* 图视图 */
.graph-view {
  animation: scaleUp 0.25s cubic-bezier(0.165, 0.84, 0.44, 1) forwards;
  display: flex;
  flex-direction: column;
  height: calc(100vh - @HEADER_HEIGHT);
  position: relative;
  width: 100vw;

  /* 数据编辑模块 */
  .data-content {
    overflow: hidden;
    position: relative;
    user-select: none;
    width: 100vw;
  }
}

.data-content {
  flex: 1;
  flex-direction: column;
  min-width: 0;

  .data-area {
    display: flex;
    flex: 1;
    height: calc(100% - 38px);

    .middle-container {
      display: flex;
      flex: 1;
      flex-direction: column;
      min-width: 0;
      position: relative;
      width: 100%;

      .data-columns {
        flex: 0 0 261px;
      }

      .data-table {
        flex: 1;
      }
    }
  }
}

/* 图内容 */
.graph-content {
  background-color: #ededf4;
  display: flex;
  width: 100%;
}

.data-bar {
  background-color: #eff0f7;
  display: flex;
  justify-content: space-between;
  padding: 0 16px;

  // 左侧 tab + icon
  .tab-left {
    display: flex;

    .data-items {
      display: flex;

      .data-item {
        padding: 5px 25px;

        &:hover {
          background-color: #f6f6f8;
        }

        &.active {
          background-color: #fafafc;
          border-top-left-radius: 5px;
          border-top-right-radius: 5px;
        }
      }
    }

    .graph-list-icon {
      color: #5d637e;
      cursor: pointer;
      font-size: 14px;
      height: 28px;
      padding: 7px 10px;
      width: 34px;
    }

    .icon-active {
      background-color: #e1e3fd;
      color: #6973ff;
    }
  }

  // 折叠 icon
  .right-side {
    align-items: center;
    display: flex;
    font-size: 12px;
  }
}

.data-empty {
  align-items: center;
  background-color: #fff;
  display: flex;
  height: 100%;
  justify-content: center;
  text-align: center;
}

.resize-data-content,
.resize-data-table-content {
  padding: 4px;

  &:hover {
    cursor: ns-resize;
  }
}

.resize-data-content {
  background-color: #eff0f7;
}

.resize-data-table-content {
  background-color: #fafafc;
}

.close {
  color: #fff;
  cursor: pointer;
  font-size: 20px;
  line-height: 64px;
  position: fixed;
  right: 20px;
  top: -60px;
}

.lasso-button {
  height: 25px;
  width: 70px;
}

.edge-config {
  background-color: #fff;
  border-radius: 4px 0 0 4px;
  height: 100%;
  overflow: hidden;
  position: absolute;
  right: 0;
  transition: width 0.3s;
  // width: 574px;
  z-index: 350;
}

.ant-modal-mask {
  background-color: rgba(0, 0, 0, 0.2);
  bottom: 0;
  filter: alpha(opacity=50);
  height: 100%;
  left: 0;
  position: fixed;
  right: 0;
  top: 0;
  z-index: 1000;
}

@keyframes scaleUp {
  0% {
    opacity: 0;
    transform: scale(0.8) translateY(1000px);
  }

  100% {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}
// @keyframes scaleDown {
//   0% {
//     opacity: 1;
//     transform: scale(1) translateY(0);
//   }

//   100% {
//     opacity: 0;
//     transform: scale(0.8) translateY(1000px);
//   }
// }
</style>
